#include "pthread.h"
#include "unistd.h"
#include "time.h"
#include "sys/time.h"
#include "PreTestMaic.h"
#include "errno.h"
#include "string.h"

volatile long g_autoValue;
long g_criticalValue;
int threadCount;
pthread_mutex_t m_mutex_t;
pthread_cond_t m_cnd_t;
pthread_mutex_t m_mutex_leave;
pthread_cond_t m_cnd_leave;

int pthread_wait_t(pthread_cond_t* cv, pthread_mutex_t* cs, int ms)
{

	struct timespec ts;
	struct timeval tp;
	int errcode = gettimeofday(&tp, NULL);
	if (errcode != 0)
	{
		return -1;
	}
	ts.tv_sec = tp.tv_sec;
	ts.tv_nsec = tp.tv_usec + ms * 1000 * 1000;       

//	return pthread_cond_timedwait(cv, cs, &ts);
	return 0;
}

void* signalEntry(void* p)
{
	while(1)
	{
		//pthread_cond_signal(&m_cnd_t);
		sleep(1);
	}
}

void* threadEntry(void* p)
{
	int i=0;
	int retCode = 0;
	for(; i < 10; ++i)
	{
		retCode = pthread_mutex_lock(&m_mutex_t);
		retCode = pthread_wait_t(&m_cnd_t, &m_mutex_t, 000);
		if(retCode != 0)
		{
			putToStdout("pthread_wait_t, failed, %d==%d, %s\r\n", retCode, ETIMEDOUT, strerror(retCode));
		}

		++g_criticalValue;
		pthread_mutex_unlock(&m_mutex_t);

		__sync_add_and_fetch(&g_autoValue, 1);
		printf("wait for next tern: %d\r\n", i);
	}
	printf("********************************************************\r\n");
	++threadCount;
	if(threadCount == 10)
	{
		pthread_cond_signal(&m_cnd_leave);
	}
	return NULL;
}	

int doTest()
{
	pthread_t pid;
	int i=0;
	int retCode = 0;
	for(; i < 10; ++i)
	{
		retCode = pthread_create(&pid, NULL, threadEntry, NULL);
		if(retCode != 0)
		{
			putToStdout("create pthread thread failed, %s\r\n", strerror(errno));
			return retCode;
		}
		pthread_detach(pid);		
	}
	pthread_create(&pid, NULL, signalEntry, NULL);
	retCode = pthread_cond_broadcast(&m_cnd_t);
	if(retCode != 0)
	{
		putToStdout("pthead_cond_signal failed\r\n");
		return -1;
	}
	pthread_mutex_lock(&m_mutex_leave);
	pthread_cond_wait(&m_cnd_leave, &m_mutex_leave);
	pthread_mutex_unlock(&m_mutex_leave);
	putToStdout("auto_ops_value=%ld, critical_ops_value=%ld\r\n", g_autoValue, g_criticalValue);
	return 0;
}


int preTestPthread()
{
	int retCode = 0;
	retCode = pthread_mutex_init(&m_mutex_t, NULL);
	if(retCode != 0)
	{
		putToStdout("pthread_mutex_init, failed, %s\r\n",strerror(retCode));
		return -1;
	}
	retCode = pthread_mutex_init(&m_mutex_leave, NULL);
	if(retCode != 0)
	{
		putToStdout("pthread_mutex_init, failed, %s\r\n",strerror(retCode));
		return -1;
	}
	
	retCode = pthread_cond_init(&m_cnd_t, NULL);
	if(retCode != 0)
	{
		putToStdout("pthread_cond_init, failed, %s\r\n",strerror(retCode));
		return -1;
	}
	retCode = pthread_cond_init(&m_cnd_leave, NULL);
	if(retCode != 0)
	{
		putToStdout("pthread_cond_init, failed, %s\r\n",strerror(retCode));
		return -1;
	}
	retCode = doTest();
	return retCode;
}
